libobs_wrapper\utils\info/
startup.rs

1use crate::{
2    context::ObsContext,
3    data::{audio::ObsAudioInfo, video::ObsVideoInfo},
4    logger::{ConsoleLogger, ObsLogger},
5    utils::{initialization::NixDisplay, ObsError, ObsPath, ObsString},
6};
7
8/// Contains information to start a libobs context.
9/// This is passed to the creation of `ObsContext`.
10///
11/// ## Platform Notes
12/// On Linux platforms, if your application uses a GUI
13/// framework (like GTK, Qt, etc.), it is crucial to set
14/// the appropriate `NixDisplay` in the `StartupInfo` **if you want to create a preview window**.
15/// This ensures that libobs can correctly interface with
16/// the display server (X11 or Wayland) used by your application.
17/// If this is not set, libobs will not be able to create a preview window and the application will crash.
18#[derive(Debug)]
19pub struct StartupInfo {
20    pub(crate) startup_paths: StartupPaths,
21    pub(crate) obs_video_info: ObsVideoInfo,
22    pub(crate) obs_audio_info: ObsAudioInfo,
23    // Option because logger is taken when creating
24    pub(crate) logger: Option<Box<dyn ObsLogger + Sync + Send>>,
25    pub(crate) start_glib_loop: bool,
26    pub(crate) nix_display: Option<NixDisplay>,
27}
28
29impl StartupInfo {
30    pub fn new() -> StartupInfo {
31        Self::default()
32    }
33
34    #[cfg_attr(coverage_nightly, coverage(off))]
35    pub fn set_startup_paths(mut self, paths: StartupPaths) -> Self {
36        self.startup_paths = paths;
37        self
38    }
39
40    pub fn set_video_info(mut self, ovi: ObsVideoInfo) -> Self {
41        self.obs_video_info = ovi;
42        self
43    }
44
45    #[cfg_attr(coverage_nightly, coverage(off))]
46    pub fn get_video_info(&self) -> &ObsVideoInfo {
47        &self.obs_video_info
48    }
49
50    #[cfg_attr(coverage_nightly, coverage(off))]
51    pub fn set_logger(mut self, logger: Box<dyn ObsLogger + Sync + Send>) -> Self {
52        self.logger = Some(logger);
53        self
54    }
55
56    #[cfg_attr(coverage_nightly, coverage(off))]
57    pub fn set_start_glib_loop(mut self, start: bool) -> Self {
58        self.start_glib_loop = start;
59        self
60    }
61
62    /// This sets the Nix display (X11 or Wayland) to use when starting libobs.
63    ///
64    /// This is **important** if your application creates any preview windows using libobs on Linux.
65    /// Otherwise if you don't plan to use preview windows **AND** are not using a GUI framework, you can skip this.
66    ///
67    /// Wayland requires this display to be the same as the one used by the GUI application (if you have one).
68    /// Failing to set this may result in libobs being unable to create preview windows,
69    ///
70    /// X11 however works without setting this display, in fact your window may become unresponsive if a display is set.
71    ///
72    /// # Safety
73    /// Make sure that the display is closed AFTER the whole OBS context has been dropped!
74    pub unsafe fn set_nix_display(mut self, display: NixDisplay) -> Self {
75        self.nix_display = Some(display);
76        self
77    }
78
79    #[cfg_attr(coverage_nightly, coverage(off))]
80    pub fn start(self) -> Result<ObsContext, ObsError> {
81        ObsContext::new(self)
82    }
83}
84
85impl Default for StartupInfo {
86    fn default() -> StartupInfo {
87        Self {
88            startup_paths: StartupPaths::default(),
89            obs_video_info: ObsVideoInfo::default(),
90            obs_audio_info: ObsAudioInfo::default(),
91            logger: Some(Box::new(ConsoleLogger::new())),
92            start_glib_loop: true,
93            nix_display: None,
94        }
95    }
96}
97
98/// Contains the necessary paths for starting the
99/// libobs context built from `ObsPath`.
100///
101/// Note that these strings are copied when parsed,
102/// meaning that these can be freed immediately
103/// after all three strings have been used.
104#[derive(Clone, Debug)]
105pub struct StartupPaths {
106    libobs_data_path: ObsString,
107    plugin_bin_path: ObsString,
108    plugin_data_path: ObsString,
109}
110
111impl StartupPaths {
112    #[cfg_attr(coverage_nightly, coverage(off))]
113    pub fn new(
114        libobs_data_path: ObsPath,
115        plugin_bin_path: ObsPath,
116        plugin_data_path: ObsPath,
117    ) -> StartupPaths {
118        Self {
119            libobs_data_path: libobs_data_path.build(),
120            plugin_bin_path: plugin_bin_path.build(),
121            plugin_data_path: plugin_data_path.build(),
122        }
123    }
124
125    pub fn libobs_data_path(&self) -> &ObsString {
126        &(self.libobs_data_path)
127    }
128
129    pub fn plugin_bin_path(&self) -> &ObsString {
130        &(self.plugin_bin_path)
131    }
132
133    pub fn plugin_data_path(&self) -> &ObsString {
134        &(self.plugin_data_path)
135    }
136}
137
138impl Default for StartupPaths {
139    fn default() -> Self {
140        StartupPathsBuilder::new().build()
141    }
142}
143
144#[derive(Clone, Debug)]
145pub struct StartupPathsBuilder {
146    libobs_data_path: ObsPath,
147    plugin_bin_path: ObsPath,
148    plugin_data_path: ObsPath,
149}
150
151impl StartupPathsBuilder {
152    fn new() -> Self {
153        #[cfg(not(target_os = "linux"))]
154        return Self {
155            libobs_data_path: ObsPath::from_relative("data/libobs"),
156            plugin_bin_path: ObsPath::from_relative("obs-plugins/64bit"),
157            plugin_data_path: ObsPath::from_relative("data/obs-plugins/%module%"),
158        };
159
160        #[cfg(target_os = "linux")]
161        let arch = std::env::consts::ARCH;
162        #[cfg(target_os = "linux")]
163        let lib_path = match arch {
164            "x86_64" => "/usr/lib/x86_64-linux-gnu",
165            "aarch64" => "/usr/lib/aarch64-linux-gnu",
166            "arm" => "/usr/lib/arm-linux-gnueabihf",
167            _ => "/usr/lib",
168        };
169
170        #[cfg(target_os = "linux")]
171        return Self {
172            libobs_data_path: ObsPath::new("/usr/share/obs/libobs"),
173            plugin_bin_path: ObsPath::new(&(lib_path.to_string() + "/obs-plugins/%module%")),
174            plugin_data_path: ObsPath::new("/usr/share/obs/obs-plugins/%module%"),
175        };
176    }
177
178    pub fn build(self) -> StartupPaths {
179        StartupPaths {
180            libobs_data_path: self.libobs_data_path.build(),
181            plugin_bin_path: self.plugin_bin_path.build(),
182            plugin_data_path: self.plugin_data_path.build(),
183        }
184    }
185
186    #[cfg_attr(coverage_nightly, coverage(off))]
187    pub fn libobs_data_path(mut self, value: ObsPath) -> Self {
188        self.libobs_data_path = value;
189        self
190    }
191
192    #[cfg_attr(coverage_nightly, coverage(off))]
193    pub fn plugin_bin_path(mut self, value: ObsPath) -> Self {
194        self.plugin_bin_path = value;
195        self
196    }
197
198    #[cfg_attr(coverage_nightly, coverage(off))]
199    pub fn plugin_data_path(mut self, value: ObsPath) -> Self {
200        self.plugin_data_path = value;
201        self
202    }
203}
204
205#[cfg_attr(coverage_nightly, coverage(off))]
206impl Default for StartupPathsBuilder {
207    fn default() -> StartupPathsBuilder {
208        Self::new()
209    }
210}